home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / libg_261.zip / libg_261 / libg++ / src / Intdouble.cc < prev    next >
C/C++ Source or Header  |  1993-11-03  |  3KB  |  143 lines

  1. /* 
  2. Copyright (C) 1988, 1993 Free Software Foundation
  3.     written by Doug Lea (dl@rocky.oswego.edu)
  4.  
  5. This file is part of the GNU C++ Library.  This library is free
  6. software; you can redistribute it and/or modify it under the terms of
  7. the GNU Library General Public License as published by the Free
  8. Software Foundation; either version 2 of the License, or (at your
  9. option) any later version.  This library is distributed in the hope
  10. that it will be useful, but WITHOUT ANY WARRANTY; without even the
  11. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  12. PURPOSE.  See the GNU Library General Public License for more details.
  13. You should have received a copy of the GNU Library General Public
  14. License along with this library; if not, write to the Free Software
  15. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  16. */
  17.  
  18. // Routines for converting between Integers and doubles.
  19. // Split up into a separate file to avoid Integer.o's need
  20. // for libm.a on some systems (including SunOS 4).
  21.  
  22. #include <Integer.h>
  23. #include "Integer.hP"
  24. #include <float.h>
  25. #include <math.h>
  26. #include <limits.h>
  27.  
  28. #ifndef HUGE_VAL
  29. #ifdef HUGE
  30. #define HUGE_VAL HUGE
  31. #else
  32. #define HUGE_VAL DBL_MAX
  33. #endif
  34. #endif
  35.  
  36. // convert to a double 
  37.  
  38. double Itodouble(const IntRep* rep)
  39.   double d = 0.0;
  40.   double bound = DBL_MAX / 2.0;
  41.   for (int i = rep->len - 1; i >= 0; --i)
  42.   {
  43.     unsigned short a = I_RADIX >> 1;
  44.     while (a != 0)
  45.     {
  46.       if (d >= bound)
  47.         return (rep->sgn == I_NEGATIVE) ? -HUGE_VAL : HUGE_VAL;
  48.       d *= 2.0;
  49.       if (rep->s[i] & a)
  50.         d += 1.0;
  51.       a >>= 1;
  52.     }
  53.   }
  54.   if (rep->sgn == I_NEGATIVE)
  55.     return -d;
  56.   else
  57.     return d;
  58. }
  59.  
  60. // see whether op double() will work-
  61. // have to actually try it in order to find out
  62. // since otherwise might trigger fp exception
  63.  
  64. int Iisdouble(const IntRep* rep)
  65. {
  66.   double d = 0.0;
  67.   double bound = DBL_MAX / 2.0;
  68.   for (int i = rep->len - 1; i >= 0; --i)
  69.   {
  70.     unsigned short a = I_RADIX >> 1;
  71.     while (a != 0)
  72.     {
  73.       if (d > bound || (d == bound && (i > 0 || (rep->s[i] & a))))
  74.         return 0;
  75.       d *= 2.0;
  76.       if (rep->s[i] & a)
  77.         d += 1.0;
  78.       a >>= 1;
  79.     }
  80.   }
  81.   return 1;
  82. }
  83.  
  84. // real division of num / den
  85.  
  86. double ratio(const Integer& num, const Integer& den)
  87. {
  88.   Integer q, r;
  89.   divide(num, den, q, r);
  90.   double d1 = q.as_double();
  91.  
  92.   if (d1 >= DBL_MAX || d1 <= -DBL_MAX || sign(r) == 0)
  93.     return d1;
  94.   else      // use as much precision as available for fractional part
  95.   {
  96.     double  d2 = 0.0;
  97.     double  d3 = 0.0; 
  98.     int cont = 1;
  99.     for (int i = den.rep->len - 1; i >= 0 && cont; --i)
  100.     {
  101.       unsigned short a = I_RADIX >> 1;
  102.       while (a != 0)
  103.       {
  104.         if (d2 + 1.0 == d2) // out of precision when we get here
  105.         {
  106.           cont = 0;
  107.           break;
  108.         }
  109.  
  110.         d2 *= 2.0;
  111.         if (den.rep->s[i] & a)
  112.           d2 += 1.0;
  113.  
  114.         if (i < r.rep->len)
  115.         {
  116.           d3 *= 2.0;
  117.           if (r.rep->s[i] & a)
  118.             d3 += 1.0;
  119.         }
  120.  
  121.         a >>= 1;
  122.       }
  123.     }
  124.  
  125.     if (sign(r) < 0)
  126.       d3 = -d3;
  127.     return d1 + d3 / d2;
  128.   }
  129. }
  130.  
  131. double
  132. Integer::as_double () const
  133. {
  134.   return Itodouble (rep);
  135. }
  136.  
  137. int
  138. Integer::fits_in_double () const
  139. {
  140.   return Iisdouble(rep);
  141. }
  142.